/*
 * CApplication.h
 *
 *  Created on: 2020年9月16日
 *      Author: chuanjiang.zh
 */

#ifndef CAPPLICATION_H_
#define CAPPLICATION_H_

#include "Application.h"
#include <functional>
#include <deque>
#include <mutex>
#include "PollTimerQueue.h"
#include "TEvent.h"


class CApplication : public Application
{
public:
	typedef std::function< void() >		Task;

	typedef std::function< void(int) >	TimerHandler;

	enum Constant
	{
		IDLE_DURATION = 1000 * 10,	/// millisecond
		OVERRUN_TIME = 1000 * 2,	/// millisecond
		QUEUE_SIZE = 1024
	};


public:
	CApplication();
	virtual ~CApplication();


	void post(Task task);
	void clearTask();

	int setTimer(uint32_t ms, TimerHandler handler);
	int setTimeout(uint32_t ms, TimerHandler handler);

	void killTimer(int tid);
	void killTimers();

	virtual void exit(int code = 0);

	/// 检测执行任务是否阻塞(超过了指定时长).
	bool isBlocking(int milliseconds);

	/// 检测任务队列是否超过指定时长.
	bool isQueueFull(int milliseconds);

	bool checkQueueFull(int milliseconds, int& curDuration);

	/// 获取任务队列时长, 单位为毫秒.
	int getQueueDuration();

	int getQueueSize();

	int64_t getCurTaskElapse();

	void postEx(const std::string& name, Task task);

protected:
	virtual void onIdle();

	virtual int run();
	

protected:
	static int64_t getTime();

protected:
	class InvokeStopWatch
	{
	public:
		InvokeStopWatch() :
			m_clock()
		{
		}

		virtual ~InvokeStopWatch()
		{
		}

		int64_t start()
		{
			m_clock = getTime();
			return m_clock;
		}

		int64_t stop()
		{
			int64_t elapse = getTime() - m_clock;
			m_clock = 0;
			return elapse;
		}

		int64_t elapse() const
		{
			if (m_clock == 0)
			{
				return 0;
			}
			return getTime() - m_clock;
		}

		int64_t getClock() const
		{
			return m_clock;
		}

		bool isStarted() const
		{
			return m_clock != 0;
		}

	private:
		std::atomic<int64_t>	m_clock;
	};

protected:
	struct TaskRecord
	{
		int64_t clock;
		std::string	name;
		Task task;

		TaskRecord():clock()
		{
		}

		TaskRecord(int64_t clk, Task t) :clock(clk), task(t)
		{
		}
	};

	typedef std::deque< TaskRecord >	TaskQueue;

protected:
	bool fetchAndHandle();
	bool fetchTask(TaskRecord& record);

	void postEvent();
	bool timedwait(int ms);

protected:
	std::atomic_bool	m_canExit;

	std::mutex		m_mutex;
	comn::Event		m_eventTask;
	TaskQueue		m_taskQueue;

	comn::PollTimerQueue*	m_timerQueue;

	InvokeStopWatch	m_invokeWatch;

	int	m_exitCode;

};

#endif /* CAPPLICATION_H_ */
